/********************************************************************************
  * @文件名:
  *     ocrwidget.cpp
  * @作者:
  *     xcl
  * @说明:
  *     该文件的主要功能是OCR控件的实现文件
  * @注意:
  *     无
  *******************************************************************************/
#include "ocrwidget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QMessageBox>
#include <QTimer>
#include <QBuffer>
#include <QSettings>
/******************************************************************************
  * @说明:
  *     构造函数
  * @参数:
  *     parent:父控件的指针
  * @返回值:
  *     无
  ****************************************************************************/
OcrWidget::OcrWidget(QWidget *parent) : QWidget(parent)
{
    QSettings *cfg = new QSettings("OcrWidgetCfg.ini", QSettings::IniFormat);
    QString apiKey = cfg->value("key").toString();
    QString secretKey = cfg->value("secret").toString();
    if(apiKey.isEmpty())
        apiKey = QString("请收入有效的apiKey");
    if(secretKey.isEmpty())
        secretKey = QString("请输入有效的secretKey");
    delete cfg;
    pScreenshotsWidget = new ScreenshotsWidget;

    pResultTextEdit = new QTextEdit;
    pResultLabel = new QLabel("结果:");
    pResultLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    pApiKeyLabel = new QLabel("      ApiKey:");
    pSecretKeyLabel = new QLabel("SecretKeyL");
    pApiKeyLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    pSecretKeyLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    pApiKeyLineEdit = new QLineEdit;

    pApiKeyLineEdit->setText(apiKey);
    pSecretKeyLabelLineEdit = new QLineEdit;
    pSecretKeyLabelLineEdit->setText(secretKey);

    pOcrButton = new QPushButton("截图识别");
    pSaveCfgButton = new QPushButton("保存配置");

    QVBoxLayout *pMainlayout = new QVBoxLayout;
    pMainlayout->addWidget(pResultLabel);
    pMainlayout->addWidget(pResultTextEdit);

    QHBoxLayout *pApiKeyLayout = new QHBoxLayout;
    pApiKeyLayout->addWidget(pApiKeyLabel);
    pApiKeyLayout->addWidget(pApiKeyLineEdit);

    QHBoxLayout *pSecretKeyLayout = new QHBoxLayout;
    pSecretKeyLayout->addWidget(pSecretKeyLabel);
    pSecretKeyLayout->addWidget(pSecretKeyLabelLineEdit);

    QHBoxLayout *pButtonLayout = new QHBoxLayout;
    pButtonLayout->addWidget(pOcrButton, Qt::AlignCenter);
    pButtonLayout->addWidget(pSaveCfgButton, Qt::AlignCenter);

    pMainlayout->addLayout(pApiKeyLayout);
    pMainlayout->addLayout(pSecretKeyLayout);
    pMainlayout->addLayout(pButtonLayout);

    setLayout(pMainlayout);
    RefreshToken();
    connect(pOcrButton, &QPushButton::clicked, this, &OcrWidget::OcrButtonClicked);
    connect(pScreenshotsWidget, &ScreenshotsWidget::ScreenShotFinishSignal, this, &OcrWidget::OcrSlot);
    connect(pSaveCfgButton, &QPushButton::clicked, this, &OcrWidget::SaveConfigSlot);
}

/******************************************************************************
  * @说明:
  *     刷新Token
  * @参数:
  *     无
  * @返回值:
  *     无
  ****************************************************************************/
void OcrWidget::RefreshToken()
{
    QString apiKey=pApiKeyLineEdit->text();
    QString secretKey=pSecretKeyLabelLineEdit->text();

    if(apiKey.isEmpty() || secretKey.isEmpty())
    {
        QMessageBox::warning(this, "警告", "ApiKey或者SecretKey不能为空");
    }
    QNetworkRequest request(QUrl(QString("http://openapi.baidu.com/oauth/2.0/token?")));
    QByteArray append = QString("grant_type=client_credentials&client_id=%1&client_secret=%2&").arg(apiKey, secretKey).toLatin1();
    request.setRawHeader("Content-Type", "application/json");//请求token
    pNetworkAccessManager = new QNetworkAccessManager(this);
    pNetworkAccessManager->post(request,append);
    connect(pNetworkAccessManager, &QNetworkAccessManager::finished, this, &OcrWidget::AccessTokenSlot);

}

/******************************************************************************
  * @说明:
  *     网络获取Token的槽函数
  * @参数:
  *     rely:QNetworkReply类的一个指针
  * @返回值:
  *     无
  ****************************************************************************/
void OcrWidget::AccessTokenSlot(QNetworkReply *rely)
{
    int errnum;
    errnum = rely->error();
    QByteArray databuff;
    if(errnum == QNetworkReply::NoError)
    {
        databuff = rely->readAll();
    }
    qDebug()<<rely;
    const auto &&data = QJsonDocument::fromJson(databuff).object();

    tokenString = data["access_token"].toString();
    pNetworkAccessManager->deleteLater();
}

/******************************************************************************
  * @说明:
  *     OCR按钮被按下时候调用的槽函数
  * @参数:
  *     无
  * @返回值:
  *     无
  ****************************************************************************/
void OcrWidget::OcrButtonClicked()
{
    QTimer::singleShot(500, pScreenshotsWidget, &ScreenshotsWidget::LoadPixmapSlot);
}

/******************************************************************************
  * @说明:
  *     进行OCR的一个槽函数
  * @参数:
  *     pixmap:需要识别图像的pixmap对象
  * @返回值:
  *     无
  ****************************************************************************/
void OcrWidget::OcrSlot(QPixmap pixmap)
{
    QImage image = pixmap.toImage();
    QByteArray ba;
    QBuffer buf(&ba);
    image.save(&buf, "jpg", 100);
    QByteArray hexed = ba.toBase64();

    QUrl url;
    url.setUrl("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token="+tokenString);

    QNetworkRequest request;
    request.setUrl(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/x-www-form-urlencoded"));
    QByteArray byteArr;
    byteArr.append("image=");
    byteArr.append(QUrl::toPercentEncoding(hexed));
    pNetworkAccessManager = new QNetworkAccessManager(this);
    pNetworkAccessManager->post(request,byteArr);
    connect(pNetworkAccessManager, &QNetworkAccessManager::finished,this, &OcrWidget::OcrResultSlot);
}

/******************************************************************************
  * @说明:
  *     获取OCR请求的结果
  * @参数:
  *     reply:网络应答类QNetworkReply的指针，通过它可以获取网络回复状态
  * @返回值:
  *     无
  ****************************************************************************/
void OcrWidget::OcrResultSlot(QNetworkReply* reply)
{
    QNetworkReply::NetworkError err = reply->error();
    if(err != QNetworkReply::NoError)
    {
        qDebug() << "Failed: " << reply->errorString();
    }else
    {
        QJsonParseError json_error;
        QJsonDocument parse_doucment = QJsonDocument::fromJson(reply->readAll(), &json_error);
        if(parse_doucment.isObject())
        {
            QJsonObject obj = parse_doucment.object();
            int wordsNum = obj.take("words_result_num").toInt();
            if(wordsNum > 0)
            {
                QString res;
                QJsonArray jsonArr = obj.take("words_result").toArray();
                for(int i=0;i<wordsNum;i++)
                {
                    res.append(jsonArr[i].toObject().take("words").toString());
                    res.append("<br>");
                }
                pResultTextEdit->setText(res);

            }
            else
            {
                QMessageBox::information(NULL, "提示", "无法识别图片内容");
            }
        }
    }
    pNetworkAccessManager->deleteLater();

}

/******************************************************************************
  * @说明:
  *     保存相关配置
  * @参数:
  *     无
  * @返回值:
  *     无
  ****************************************************************************/
void OcrWidget::SaveConfigSlot()
{
    QString apiKeyString = pApiKeyLineEdit->text();
    QString secretKeyString =pSecretKeyLabelLineEdit->text();
    QSettings *cfg = new QSettings("OcrWidgetCfg.ini", QSettings::IniFormat);
    cfg->setValue("key", apiKeyString);
    cfg->setValue("secret", secretKeyString);
    delete cfg;
    QMessageBox::information(NULL, "成功", "保存成功");
    RefreshToken();
}
